﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.templates;
using l1cs.server.serverpackets;
using System.Threading;

namespace l1cs.server.model.Instance
{
    public class L1TowerInstance : L1NpcInstance
    {
        private static Logger _log = Logger.getLogger( typeof( L1TowerInstance ).FullName );

        public L1TowerInstance( L1Npc template ) : base( template ) { }

        private L1Character _lastattacker;
        private int _castle_id;
        private int _crackStatus;

        override public void onPerceive( L1PcInstance perceivedFrom )
        {
            perceivedFrom.addKnownObject( this );
            perceivedFrom.sendPackets( new S_NPCPack( this ) );
        }

        override public void onAction( L1PcInstance player )
        {
            if ( getCurrentHp() > 0 && !isDead() )
            {
                L1Attack attack = new L1Attack( player, this );
                if ( attack.calcHit() )
                {
                    attack.calcDamage();
                    attack.addPcPoisonAttack( player, this );
                    attack.addChaserAttack();
                }
                attack.action();
                attack.commit();
            }
        }

        override public void receiveDamage( L1Character attacker, int damage )
        { // 攻撃でＨＰを減らすときはここを使用
            if ( _castle_id == 0 )
            { // 初期設定で良いがいい場所がない
                if ( isSubTower() )
                {
                    _castle_id = L1CastleLocation.ADEN_CASTLE_ID;
                }
                else
                {
                    _castle_id = L1CastleLocation.getCastleId( getX(), getY(),
                            getMapId() );
                }
            }

            if ( _castle_id > 0
                    && WarTimeController.getInstance().isNowWar( _castle_id ) )
            { // 戦争時間内

                // アデン城のメインタワーはサブタワーが3つ以上破壊されている場合のみ攻撃可能
                if ( _castle_id == L1CastleLocation.ADEN_CASTLE_ID
                        && !isSubTower() )
                {
                    int subTowerDeadCount = 0;
                    foreach ( L1Object l1object in L1World.getInstance().getObject() )
                    {
                        if ( l1object is L1TowerInstance )
                        {
                            L1TowerInstance tower = (L1TowerInstance)l1object;
                            if ( tower.isSubTower() && tower.isDead() )
                            {
                                subTowerDeadCount++;
                                if ( subTowerDeadCount == 4 )
                                {
                                    break;
                                }
                            }
                        }
                    }
                    if ( subTowerDeadCount < 3 )
                    {
                        return;
                    }
                }

                L1PcInstance pc = null;
                if ( attacker is L1PcInstance )
                {
                    pc = (L1PcInstance)attacker;
                }
                else if ( attacker is L1PetInstance )
                {
                    pc = (L1PcInstance)( (L1PetInstance)attacker ).getMaster();
                }
                else if ( attacker is L1SummonInstance )
                {
                    pc = (L1PcInstance)( (L1SummonInstance)attacker ).getMaster();
                }
                if ( pc == null )
                {
                    return;
                }

                // 布告しているかチェック。但し、城主が居ない場合は布告不要
                bool existDefenseClan = false;
                foreach ( L1Clan clan in L1World.getInstance().getAllClans() )
                {
                    int clanCastleId = clan.getCastleId();
                    if ( clanCastleId == _castle_id )
                    {
                        existDefenseClan = true;
                        break;
                    }
                }
                bool isProclamation = false;
                // 全戦争リストを取得
                foreach ( L1War war in L1World.getInstance().getWarList() )
                {
                    if ( _castle_id == war.GetCastleId() )
                    { // 今居る城の戦争
                        isProclamation = war.CheckClanInWar( pc.getClanname() );
                        break;
                    }
                }
                if ( existDefenseClan == true && isProclamation == false )
                { // 城主が居て、布告していない場合
                    return;
                }

                if ( getCurrentHp() > 0 && !isDead() )
                {
                    int newHp = getCurrentHp() - damage;
                    if ( newHp <= 0 && !isDead() )
                    {
                        setCurrentHpDirect( 0 );
                        setDead( true );
                        setStatus( ActionCodes.ACTION_TowerDie );
                        _lastattacker = attacker;
                        _crackStatus = 0;
                        // TODO 優先度9 スレッドプール
                        //Death death = new Death();
                        //GeneralThreadPool.getInstance().execute(death);
                        l1object = L1World.getInstance().findObject( getId() );
                        npc = (L1TowerInstance)l1object;
                        ThreadPool.QueueUserWorkItem( new WaitCallback( DeathThreasSub ) );
                        // Death(attacker);
                    }
                    if ( newHp > 0 )
                    {
                        setCurrentHp( newHp );
                        if ( ( getMaxHp() * 1 / 4 ) > getCurrentHp() )
                        {
                            if ( _crackStatus != 3 )
                            {
                                broadcastPacket( new S_DoActionGFX( getId(),
                                        ActionCodes.ACTION_TowerCrack3 ) );
                                setStatus( ActionCodes.ACTION_TowerCrack3 );
                                _crackStatus = 3;
                            }
                        }
                        else if ( ( getMaxHp() * 2 / 4 ) > getCurrentHp() )
                        {
                            if ( _crackStatus != 2 )
                            {
                                broadcastPacket( new S_DoActionGFX( getId(),
                                        ActionCodes.ACTION_TowerCrack2 ) );
                                setStatus( ActionCodes.ACTION_TowerCrack2 );
                                _crackStatus = 2;
                            }
                        }
                        else if ( ( getMaxHp() * 3 / 4 ) > getCurrentHp() )
                        {
                            if ( _crackStatus != 1 )
                            {
                                broadcastPacket( new S_DoActionGFX( getId(),
                                        ActionCodes.ACTION_TowerCrack1 ) );
                                setStatus( ActionCodes.ACTION_TowerCrack1 );
                                _crackStatus = 1;
                            }
                        }
                    }
                }
                else if ( !isDead() )
                { // 念のため
                    setDead( true );
                    setStatus( ActionCodes.ACTION_TowerDie );
                    _lastattacker = attacker;
                    // TODO 優先度9 スレッドプール
                    //Death death = new Death();
                    //GeneralThreadPool.getInstance().execute(death);
                    l1object = L1World.getInstance().findObject( getId() );
                    npc = (L1TowerInstance)l1object;
                    ThreadPool.QueueUserWorkItem( new WaitCallback( DeathThreasSub ) );
                    // Death(attacker);
                }
            }
        }

        override public void setCurrentHp( int i )
        {
            int currentHp = i;
            if ( currentHp >= getMaxHp() )
            {
                currentHp = getMaxHp();
            }
            setCurrentHpDirect( currentHp );
        }

        //class Death
        //{
        //L1Character lastAttacker = _lastattacker;
        L1Object l1object;
        L1TowerInstance npc;

        public void DeathThreasSub( object state )
        {
            setCurrentHpDirect( 0 );
            setDead( true );
            setStatus( ActionCodes.ACTION_TowerDie );
            int targetobjid = npc.getId();

            npc.getMap().setPassable( npc.getLocation(), true );

            npc.broadcastPacket( new S_DoActionGFX( targetobjid,
                    ActionCodes.ACTION_TowerDie ) );

            // クラウンをspawnする
            if ( !isSubTower() )
            {
                L1WarSpawn warspawn = new L1WarSpawn();
                warspawn.SpawnCrown( _castle_id );
            }
            //}
        }

        override public void deleteMe()
        {
            _destroyed = true;
            if ( getInventory() != null )
            {
                getInventory().clearItems();
            }
            allTargetClear();
            _master = null;
            L1World.getInstance().removeVisibleObject( this );
            L1World.getInstance().removeObject( this );
            foreach ( L1PcInstance pc in L1World.getInstance().getRecognizePlayer( this ) )
            {
                pc.removeKnownObject( this );
                pc.sendPackets( new S_RemoveObject( this ) );
            }
            removeAllKnownObjects();
        }

        public bool isSubTower()
        {
            return ( getNpcTemplate().get_npcId() == 81190
                    || getNpcTemplate().get_npcId() == 81191
                    || getNpcTemplate().get_npcId() == 81192
                    || getNpcTemplate().get_npcId() == 81193 );
        }
    }
}
